
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mm_types.h>

#include <linux/sched.h>
#include <linux/sched/task.h>

#include <linux/page-flags.h>



// 定义数据结构来跟踪页面分配
struct alloc_event {
    u32 pid;
    u32 tid;
    u64 timestamp;
    u64 gfp_flags;
    u32 order;
    u64 page_addr;
    u32 nr_pages;
    char comm[16];
};

BPF_HASH(alloc_cache, u64, struct alloc_event);
// 定义Perf事件映射
BPF_PERF_OUTPUT(alloc_events);


// 跟踪页面分配函数
int trace_alloc_pages_entry(struct pt_regs *ctx, gfp_t gfp_mask, unsigned int order) {
    u64 id = bpf_get_current_pid_tgid();
    u32 pid = id >> 32;
    
    // 进程过滤


    struct task_struct *task = (struct task_struct *)bpf_get_current_task();
    char comm[16];
    bpf_probe_read_kernel_str(comm, sizeof(comm), task->comm);

    struct alloc_event event = {};
    event.pid = pid;
    event.tid = (u32)id;
    event.timestamp = bpf_ktime_get_ns();
    event.gfp_flags = gfp_mask;
    event.order = order;
    event.nr_pages = 1 << order;
    __builtin_memcpy(event.comm, comm, sizeof(comm));

    u64 key = pid;
    alloc_cache.update(&key, &event);

    return 0;
}



int trace_alloc_pages_return(struct pt_regs *ctx) {
    u64 id = bpf_get_current_pid_tgid();
    u32 pid = id >> 32;
    u64 key = pid;

    struct alloc_event *event = alloc_cache.lookup(&key);
    if (!event) return 0;

    event->page_addr = PT_REGS_RC(ctx);
    alloc_events.perf_submit(ctx, event, sizeof(*event));
    alloc_cache.delete(&key);

    return 0;
}


